package com.bootdo.app.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bootdo.common.configure.dao.DictDao;
import com.bootdo.common.configure.domain.DictDO;
import com.bootdo.common.utils.*;
import com.bootdo.system.dao.AppVersionDao;
import com.bootdo.system.domain.AppVersionDO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bootdo.app.domain.PayeeAppDO;
import com.bootdo.app.service.AppLoginService;
import com.bootdo.cash.dao.CashDao;
import com.bootdo.common.config.Constant;
import com.bootdo.common.redis.lock.CommonRedisLock;
import com.bootdo.essential.dao.BankDao;
import com.bootdo.essential.domain.BankDO;
import com.bootdo.merchant.dao.MerchantDao;
import com.bootdo.merchant.domain.MerchantDO;
import com.bootdo.mq.RabbitUtil;
import com.bootdo.mq.SendSortUtil;
import com.bootdo.order.task.LowerTask;
import com.bootdo.order.task.RequestTask;
import com.bootdo.order.dao.OrderDao;
import com.bootdo.order.dao.OrderPayDao;
import com.bootdo.order.dao.ReceiptDao;
import com.bootdo.order.domain.OrderDO;
import com.bootdo.order.domain.OrderPayDO;
import com.bootdo.order.domain.ReceiptDO;
import com.bootdo.payee.dao.PassagewayDao;
import com.bootdo.payee.dao.PayeeAgentDao;
import com.bootdo.payee.dao.PayeeDao;
import com.bootdo.payee.dao.PaymentCodeDao;
import com.bootdo.payee.domain.PassagewayDO;
import com.bootdo.payee.domain.PayeeAgentDO;
import com.bootdo.payee.domain.PayeeDO;
import com.bootdo.payee.domain.PaymentCodeDO;
import com.bootdo.quota.dao.QuotaDao;
import com.bootdo.quota.domain.QuotaDO;
import com.bootdo.rate.dao.RateDao;
import com.bootdo.rate.domain.RateDO;
import com.bootdo.system.dao.UserDao;
import com.bootdo.system.domain.UserDO;

/**
 * @Desc
 * @date 2019/11/20
 *
 */
@Service
public class AppLoginServiceImpl implements AppLoginService {

    private static Logger logger = LoggerFactory.getLogger(AppLoginServiceImpl.class);

    @Autowired
    private PayeeDao payeeMapper;
    @Autowired
    private OrderDao orderMapper;
    @Autowired
    private PaymentCodeDao paymentCodeMapper;
    @Autowired
    private PassagewayDao passagewayMapper;
    @Autowired
    private QuotaDao quotaMapper;
    @Autowired
    private OrderPayDao orderPayMapper;
    @Autowired
    private ReceiptDao receiptMapper;
    @Autowired
    private MerchantDao merchantMapper;
    @Autowired
    private CashDao cashMapper;
    @Autowired
    private BankDao bankMapper;
    @Autowired
    private PayeeAgentDao payeeAgentMapper;
    @Autowired
    private UserDao userMapper;
    @Autowired
    private AppVersionDao appVersionMapper;
    @Autowired
    private RateDao rateMapper;
    @Autowired
    private DictDao dictMapper;
    @Autowired
    private RabbitUtil rabbitUtil;
    @Autowired
    private SendSortUtil sendSortUtil;
    @Autowired
    protected StringRedisTemplate stringRedisTemplate;

    @Value("${bootdo.uploadPath}")
    private String url;
    @Value("${bootdo.path}")
    private String paths;

    //存储订单编号
    private final String ORDER_ID_CONFIRM = "ORDER_ID_CONFIRM";


    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public String login(String userName, String password, String deviceId) throws Exception{
        logger.info("收到用户登录请求：username【"+userName+"】，password【"+password+"】，deviceId【"+deviceId+"】");
        password = MD5Utils.encrypt(userName, password);
        Map<String, Object> map = new HashMap<>();
        map.put("userName", userName);
        map.put("password", password);
        PayeeDO payee = payeeMapper.getByUserNameP(map);
        if (payee == null) {
            throw new Exception("账号或密码错误");
        }

        if (StringUtils.isNotBlank(payee.getDeviceId()) && !deviceId.equals(payee.getDeviceId())){
            throw new Exception("当前用户登录设备异常，请联系管理员");
        }

        if (1 != payee.getStatus().intValue()){
            throw new Exception("当前用户已被禁用，请联系管理员");
        }

        if (StringUtils.isNotBlank(deviceId) && StringUtils.isBlank(payee.getDeviceId())){
            payee.setDeviceId(deviceId);
            payeeMapper.update(payee);
        }

        PayeeAgentDO payeeAgent = payeeAgentMapper.get(payee.getUserIdCreate());
        if (payeeAgent == null || payeeAgent.getStatus().intValue() == 0){
            throw new Exception("当前收款户代理不存在，请联系管理员");
        }
        if (1 == payee.getLineUpStatus() && 1 == payee.getLineStatus()) {
            List<OrderDO> list = orderMapper.getOrderByPayeeForNo(payee.getUserId());
            QuotaDO quota = quotaMapper.get(payee.getUserId());
            if (payee.getUncollectedQuantity().intValue() >= list.size() && quota.getActualQuota().doubleValue() > 0.0){
                //获取当前用户使用的收款通道
                PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
                if (paymentCode != null) {
                    //根据用户排队通道以及userId获取用户是否存在排队
                    CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
                    boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
                    if (!f){
                        commonRedisLock.lRightPush(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
                    }
                    //推送排队信息
                    sendSortUtil.sendMsg(paymentCode.getPassagewayId());
                } else {
                    payee.setLineUpStatus(0);
                    payee.setLineStatus(0);
                    payeeMapper.update(payee);
                }
            }
        }
        return payee.getUserId().toString();
    }

    @Override
    public PayeeAppDO findUser(String userId) throws Exception{
        logger.info("收到用户获取基本信息数据："+userId);
        if (StringUtils.isBlank(userId)){
            throw new Exception("必传项为空");
        }
        PayeeDO payee = payeeMapper.get(Long.valueOf(userId));
        PayeeAppDO payeeApp = new PayeeAppDO();
        payeeApp.setUserId(payee.getUserId());
        QuotaDO quota = quotaMapper.get(payee.getUserId());
        payeeApp.setQuota(quota.getActualQuota());
        payeeApp.setLineUpStatus(payee.getLineUpStatus());
        payeeApp.setLineStatus(payee.getLineStatus());

        double moneyCount = 0.00;
        List<OrderPayDO> orderPayDOList = orderPayMapper.getPayMentingByUserId(payee.getUserId());
        if (orderPayDOList!=null&&orderPayDOList.size()>0) {
            for (OrderPayDO orderPay:orderPayDOList) {
                if(DateUtils.isOvertime(orderPay.getGmtCreate())){
                    moneyCount += orderPay.getOrderMoney();
                }
            }
        }
        payeeApp.setPayMoney(moneyCount);
        return payeeApp;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int updateStatus(String userId, String status, String deviceId) throws Exception{
        int count = 0;
        logger.info("接收到用户修改用户自动接单状态信息："+userId+"，状态数据："+status+"，设备编码："+deviceId);
        CommonRedisLock commonLock = new CommonRedisLock(stringRedisTemplate,"updateStatus"+userId);
        try {
            if (commonLock.tryLock(3)) {
                PayeeDO payee = payeeMapper.get(Long.valueOf(userId));
                if (payee.getLineStatus() == 0){
                    commonLock.unlock();
                    throw new Exception("不存在排队权限");
                }
                if (payee.getStatus() == 0){
                    commonLock.unlock();
                    throw new Exception("当前用户未启用");
                }
                if (!deviceId.equals(payee.getDeviceId())){
                    commonLock.unlock();
                    // throw new Exception("当前用户登录设备异常，请联系管理员");
                    return -2;
                }
                PayeeAgentDO payeeAgent = payeeAgentMapper.get(payee.getUserIdCreate());
                if (payeeAgent == null) {
                    commonLock.unlock();
                    throw new Exception("当前收款户不存在收款代理，请联系管理员");
                } else {
                    if (payeeAgent.getStatus().intValue() == 0){
                        commonLock.unlock();
                        throw new Exception("当前收款户代理已被禁用，请联系管理员");
                    } else {
                        QuotaDO quota = quotaMapper.get(payeeAgent.getUserId());
                        if (quota.getActualQuota().doubleValue() <= 0.0){
                            commonLock.unlock();
                            throw new Exception("当前收款户代理余额不足");
                        } else {
                            quota = quotaMapper.get(payee.getUserId());
                            if (quota.getActualQuota().doubleValue() <= 0.0) {
                                commonLock.unlock();
                                throw new Exception("当前收款户余额不足");
                            }
                        }
                    }
                }

                //获取当前用户未回单数量
                List<OrderDO> list = orderMapper.getOrderByPayeeForNo(payee.getUserId());
                //验证用户是否开启通道
                PassagewayDO passageway = passagewayMapper.getPassageOk(payee.getUserId());
                if (passageway == null){
                    commonLock.unlock();
                    throw new Exception("未开启收款通道");
                }
                //获取当前用户使用的收款通道
                PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
                if (paymentCode == null){
                    commonLock.unlock();
                    throw new Exception("收款二维码未开启或二维码未审核通过");
                } /*else if ("2".equals(paymentCode.getAuditStatus())) {
                    commonLock.unlock();
                    throw new Exception("当前收款码无法正常使用，请重新上传收款码");
                } else if ("0".equals(paymentCode.getAuditStatus())) {
                    commonLock.unlock();
                    throw new Exception("当前收款码待审核，请联系管理员");
                }*/
                //获取当前用户费率
                RateDO rate = rateMapper.getRate(payee.getUserId(), paymentCode.getPassagewayId());
                if (rate == null){
                    commonLock.unlock();
                    throw new Exception("当前账号暂未设置费率");
                }
                if ("1".equals(status)){
                    if (payee.getUncollectedQuantity() > list.size()){
                        payee.setLineUpStatus(1);
                        //根据用户排队通道以及userId获取用户是否存在排队
                        CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
                        boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
                        if (!f){
                            commonRedisLock.lRightPush(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
                        }
                    } else {
                        commonLock.unlock();
                        throw new Exception("当前用户未回单数量超限");
                    }
                } else {
                    CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
                    boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
                    if (f){
                        commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(payee.getUserId()));
                    }
                    //退出排队，删除用户接单二维码
                    logger.info("<=======删除二维码并退出排队=======>");
                    paymentCodeMapper.paymentCodeDelete(paymentCode);
                    payee.setLineUpStatus(0);
                }
                sendSortUtil.sendMsg(paymentCode.getPassagewayId());
                count = payeeMapper.update(payee);
            }
        } catch (Exception e) {
            logger.error("=====修改用户状态=====>" + ExceptionUtils.getStackTraceAsString(e));
            throw e;
        } finally {
            commonLock.unlock();
        }
        return count;
    }


    @Override
    public R userPassagewayList (PassagewayDO passageway) throws Exception{
        logger.info("接收到用户获取收款通道列表信息："+JSONObject.toJSONString(passageway));
        List<PassagewayDO> userPassagewayList = passagewayMapper.userPassagewayListByJoin(passageway);
        if(userPassagewayList == null || userPassagewayList.size() <= 0){
            return R.error(-1,"暂未查询到当前使用通道");
        }
        return R.ok(userPassagewayList);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int editPassagewayStatus(PassagewayDO passageway) throws Exception {
        logger.info("接收到用户修改收款通道状态信息："+JSONObject.toJSONString(passageway));
        PassagewayDO passageways = passagewayMapper.getPassageOk(passageway.getUserId());
        Date date = new Date();
        passageway.setGmtModified(date);
        int count = passagewayMapper.update(passageway);
        //退出其他通道排队
        PayeeDO payee = payeeMapper.get(passageway.getUserId());
        logger.debug("==================排队用户信息==================>" + JSON.toJSONString(payee));
        if (1 == payee.getLineUpStatus().intValue() && passageways != null){
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + passageways.getPassagewayType(), String.valueOf(payee.getUserId()));
            if (f){
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                commonRedisLock.lRemove(Constant.PASSAGEWAY + passageways.getPassagewayType(), 0, String.valueOf(payee.getUserId()));
                //删除二维码
                PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(passageway.getUserId());
                if (passageways.getPassagewayType().equals(paymentCode.getPassagewayId())){
                    paymentCodeMapper.paymentCodeDelete(paymentCode);
                }
                sendSortUtil.sendMsg(passageways.getPassagewayType());
            }
        }

        //关闭当前用户下所有的二维码
        PaymentCodeDO paymentCode = new PaymentCodeDO();
        paymentCode.setUserIdCreate(passageway.getUserId());
        paymentCode.setGmtModified(date);
        paymentCodeMapper.closeUserAllpassagewayCode(paymentCode);

        //关闭其他通道
        if (1 == passageway.getStatus()){
            PassagewayDO passagewayDO = new PassagewayDO();
            passagewayDO.setPassagewayId(passageway.getPassagewayId());
            passagewayDO.setUserId(passageway.getUserId());
            passagewayDO.setGmtModified(date);
            passagewayMapper.closeUserOtherAllpassageway(passagewayDO);
        }
        return count;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int passagewaySave(PassagewayDO passageway) throws Exception {
        logger.info("接收到用户新增收款通道信息："+JSONObject.toJSONString(passageway));
        //退出排队
        PassagewayDO passageways = passagewayMapper.getPassageOk(passageway.getUserId());
        if (passageways != null){
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + passageways.getPassagewayType(), String.valueOf(passageways.getUserId()));
            if (f){
                PayeeDO payee = payeeMapper.get(passageways.getUserId());
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);

                commonRedisLock.lRemove(Constant.PASSAGEWAY + passageways.getPassagewayType(), 0, String.valueOf(payee.getUserId()));
                sendSortUtil.sendMsg(passageways.getPassagewayType());
            }
        }
        Date date = new Date();
        PassagewayDO passagewayDO = new PassagewayDO();
        passagewayDO.setUserId(passageway.getUserId());
        passagewayDO.setGmtModified(date);
        passagewayMapper.closeUserOtherAllpassageway(passagewayDO);

        passageway.setGmtCreate(date);
        passageway.setStatus(1);
        int count = passagewayMapper.passagewaySave(passageway);

        PaymentCodeDO paymentCode = new PaymentCodeDO();
        paymentCode.setBelongPassageway(passageway.getPassagewayId());
        paymentCode.setGmtModified(date);
        paymentCode.setUserIdCreate(passageway.getUserId());
        paymentCodeMapper.closeUserOtherAllpassagewayCode(paymentCode);
        return count;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int passagewayDelete(PassagewayDO passageway) throws Exception {
        logger.info("接收到用户删除收款通道信息："+JSONObject.toJSONString(passageway));
        //获取当面通道下开启的码
        PaymentCodeDO paymentCode = paymentCodeMapper.getByPassagewey(passageway.getPassagewayId());
        if (paymentCode != null) {
            //验证当前用户是否正在排队
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + passageway.getPassagewayType(), String.valueOf(passageway.getUserId()));
            if (f){
                PayeeDO payee = payeeMapper.get(passageway.getUserId());
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                commonRedisLock.lRemove(Constant.PASSAGEWAY + passageway.getPassagewayType(), 0, String.valueOf(payee.getUserId()));
                sendSortUtil.sendMsg(passageway.getPassagewayType());
            }
        }

        int count = passagewayMapper.passagewayDelete(passageway);
        paymentCode = new PaymentCodeDO();
        paymentCode.setBelongPassageway(passageway.getPassagewayId());
        paymentCodeMapper.passagewayCodeDelete(paymentCode);
        return count;
    }

    /**
     * 收款码新增
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public R paymentCodeSave(PaymentCodeDO paymentCode) throws Exception{
        logger.info("接收到用户上传新增收款码信息："+JSONObject.toJSONString(paymentCode));
        Date date = new Date();
        paymentCode.setGmtCreate(date);
        paymentCode.setReceivingAccount(1);
        paymentCode.setQrCode(paymentCode.getQrCode().trim());
        int count = paymentCodeMapper.paymentCodeSave(paymentCode);
        if(count != 1){
            return R.error(-1,"收款码新增失败");
        }
        Long codeId = paymentCode.getCodeId();
        PaymentCodeDO paymentCodeDO = new PaymentCodeDO();
        paymentCodeDO.setCodeId(codeId);
        paymentCodeDO.setUserIdCreate(paymentCode.getUserIdCreate());
        paymentCodeDO.setGmtModified(date);
        paymentCodeDO.setBelongPassageway(paymentCode.getBelongPassageway());
        int i = paymentCodeMapper.closeUserPassagewayOtherCode(paymentCodeDO);
        if(i < 0){
            return R.error(-1,"修改数据出错");
        }

        return R.ok();

    }

    /**
     * 收款码新增2
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int paymentCodeSave2(PaymentCodeDO paymentCode) throws Exception{
        logger.info("接收到用户【"+paymentCode.getUserIdCreate()+"】上传新增支付通道【"+paymentCode.getPassagewayId()+"】收款码信息，所属通道："+paymentCode.getBelongPassageway());
        if (StringUtils.isBlank(paymentCode.getQrCode())){
            throw new Exception("收款码为空");
        }

        DictDO dictDO = new DictDO();
        dictDO.setType("paymentCodeAudit");
        dictDO.setIsShow(1);

        dictDO = dictMapper.getDictByType(dictDO);
        if (paymentCode.getPassagewayId()!=4) {
            //将base64转为图片并保存在本地
            String base64 = paymentCode.getQrCode().trim();
            if (!Constant.PATTERN.matcher(base64).matches()){
                String fileName = StringUtils.getUUIDStr(20 ).toLowerCase();
                //不是全部为数字，则证明是二维码
                if (StringUtils.isBlank(paymentCode.getQrCodeType())){
                    paymentCode.setQrCodeType("png");
                }
                fileName += "." + paymentCode.getQrCodeType();
                String path = UploadUtils.upload(url, fileName, "1", base64);
                paymentCode.setQrCode(paths + path);
            }
        }

        Date date = new Date();
        paymentCode.setGmtCreate(date);
        paymentCode.setGmtModified(date);
        paymentCode.setReceivingAccount(1);
        if (dictDO==null || "1".equals(dictDO.getValue())) {
            //如果审核收款码状态为1或者为空，则自动设置为审核通过
            paymentCode.setAuditStatus("1");
        } else {
            //待审核
            paymentCode.setAuditStatus("0");
        }
        logger.info("=========解析后入库的二维码信息========>" + paymentCode.toString());
        int count = paymentCodeMapper.paymentCodeSave(paymentCode);
        Long codeId = paymentCode.getCodeId();
        PaymentCodeDO paymentCodeDO = new PaymentCodeDO();
        paymentCodeDO.setCodeId(codeId);
        paymentCodeDO.setUserIdCreate(paymentCode.getUserIdCreate());
        paymentCodeDO.setGmtModified(date);
        paymentCodeDO.setBelongPassageway(paymentCode.getBelongPassageway());
        paymentCodeMapper.closeUserPassagewayOtherCode(paymentCodeDO);

        return count;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int paymentCodeDelete(PaymentCodeDO paymentCode) throws Exception {
        logger.info("接收到用户删除收款码信息："+JSONObject.toJSONString(paymentCode.getCodeId()));
        paymentCode = paymentCodeMapper.get(paymentCode.getCodeId());
        if (paymentCode != null && 1 == paymentCode.getReceivingAccount().intValue()) {
            //验证当前用户是否正在排队
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(paymentCode.getUserIdCreate()));
            if (f){
                PayeeDO payee = new PayeeDO();
                payee.setUserId(paymentCode.getUserIdCreate());
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(paymentCode.getUserIdCreate()));
                sendSortUtil.sendMsg(paymentCode.getPassagewayId());
            }
        }
        return paymentCodeMapper.paymentCodeDelete(paymentCode);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int editPaymentCodeRecAcc(PaymentCodeDO paymentCode) throws Exception {
        logger.info("接收到用户修改收款码状态信息："+JSONObject.toJSONString(paymentCode.getCodeId()));
        Date date = new Date();
        paymentCode.setGmtModified(date);
        int update = paymentCodeMapper.update(paymentCode);
        //验证当前用户是否正在排队
        paymentCode = paymentCodeMapper.get(paymentCode.getCodeId());
        if (paymentCode != null) {
            //验证当前用户是否正在排队
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(paymentCode.getUserIdCreate()));
            if (f){
                PayeeDO payee = new PayeeDO();
                payee.setUserId(paymentCode.getUserIdCreate());
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(paymentCode.getUserIdCreate()));
                sendSortUtil.sendMsg(paymentCode.getPassagewayId());
            }
        }

        if(paymentCode.getReceivingAccount() == 1 && update == 1){
            PaymentCodeDO paymentCodeDO = new PaymentCodeDO();
            paymentCodeDO.setCodeId(paymentCode.getCodeId());
            paymentCodeDO.setUserIdCreate(paymentCode.getUserIdCreate());
            paymentCodeDO.setGmtModified(date);
            paymentCodeDO.setBelongPassageway(paymentCode.getBelongPassageway());
            paymentCodeMapper.closeUserPassagewayOtherCode(paymentCodeDO);
        }
        return update;
    }

    @Override
    public R userPassagewayCodeList(PaymentCodeDO paymentCode) throws Exception {
        logger.info("获取用户当前使用收款码列表："+JSONObject.toJSONString(paymentCode.getUserIdCreate()));
        List<PaymentCodeDO> userPassagewayCodeList = paymentCodeMapper.userPassagewayCodeList(paymentCode);
        for (PaymentCodeDO paymentCodes : userPassagewayCodeList){
            if (paymentCodes.getPassagewayId().intValue() == 2){
                if (paymentCodes.getQrCode().indexOf("wxp") > -1){
                    paymentCodes.setQrCode(paymentCodes.getQrCode().substring(0, paymentCodes.getQrCode().indexOf("?")));
                }
            }
        }
        if(userPassagewayCodeList == null || userPassagewayCodeList.size() <= 0){
            return R.error(-1,"暂未查询到收款码");
        }
        return R.ok(userPassagewayCodeList);
    }

    @Override
    public R queryUserOrderPayList(OrderPayDO orderPay) throws Exception {
        logger.info("获取用户订单查询列表："+JSONObject.toJSONString(orderPay));
        if (orderPay.getPayeeId() == null || orderPay.getDeviceId() == null) {
            throw new Exception("缺少必填项");
        }
        PayeeDO payee = payeeMapper.get(orderPay.getPayeeId());
        if (!orderPay.getDeviceId().equals(payee.getDeviceId())){
            return R.error(-2,"当前用户登录设备异常，请联系管理员");
        }

        if (StringUtils.isNotBlank(orderPay.getStartTime())){
            orderPay.setStartTime(DateUtils.getDateOfFormat(orderPay.getStartTime(), "yyyy-MM-dd HH:mm:SS"));
            orderPay.setEndTime(DateUtils.getDateOfFormat(orderPay.getEndTime(), "yyyy-MM-dd HH:mm:SS"));
        }

        List<OrderPayDO> queryUserOrderPayList = orderPayMapper.queryUserOrderPayList(orderPay);
        if(queryUserOrderPayList == null || queryUserOrderPayList.size() <= 0){
            return R.error(-1,"暂未查询到当前用户符合条件的订单");
        }

        return R.ok(queryUserOrderPayList);

    }

    @Override
    public R queryUserOrderPayIncomeData(OrderPayDO orderPay) throws Exception {
        logger.info("获取用户统计订单数据信息列表："+JSONObject.toJSONString(orderPay));
        List<Map<String,Object>> list = orderPayMapper.queryUserOrderPayIncomeDataBySql(orderPay);
        Map<String,Object> result = new HashMap<>();
        for (Map<String, Object> map : list) {
            result.put(String.valueOf(map.get("dayStr")), map.get("income"));
        }
        return R.ok(result);
    }

    @Override
    public R queryPayeeAgentBankByPayeeId(Long userId) throws Exception {
        logger.info("获取用户当前用户查询收款户代理信息："+JSONObject.toJSONString(userId));
        PayeeDO payee = payeeMapper.get(userId);
        BankDO bank = bankMapper.getByUser(payee.getUserIdCreate());
        if(bank == null){
            return R.error(-1,"暂未查询当前收款户对应代理银行信息");
        }
        return R.ok(bank);
    }


    @Override
    public R queryPayeeAgentBankByOrderId(String orderId) throws Exception {
        logger.info("获取用户当前用户查询收款户代理信息："+JSONObject.toJSONString(orderId));
        OrderPayDO orderPayDO = orderPayMapper.getByOrderId(orderId);
        BankDO bank = bankMapper.getByUser(orderPayDO.getPayeeAgentId());
        if(bank == null){
            return R.error(-1,"暂未查询当前收款户对应代理银行信息");
        }
        return R.ok(bank);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public R uploadReceipt(ReceiptDO receipt) throws Exception {
        if (receipt.getVoucher() == null || receipt.getVoucher().length()==0){
            return R.error(-1,"回单上传失败，缺少回单凭证");
        }
        if (receipt == null || StringUtils.isBlank(receipt.getOrderId())){
            return R.error(-1,"回单上传失败，缺少必要参数");
        }

        CommonRedisLock commonRedisLock = null;
        CommonRedisLock commonRedisLocks = new CommonRedisLock(stringRedisTemplate);
        try{
            commonRedisLock = new CommonRedisLock(stringRedisTemplate, Constant.ORDER_RECEIPT + receipt.getOrderId());
            if(!commonRedisLock.tryLock(3)){
                logger.debug("===========当前订单已点击回单===========>" + receipt.getOrderId());
                return R.error(-1,"当前订单已点击回单，请等待");
            }

            logger.info("接收到用户上传凭证信息："+JSON.toJSONString(receipt));
            //获取当前订单是否存在审核
            if (commonRedisLocks.searchListByValue(Constant.ORDER_RECEIPT, receipt.getOrderId())){
                logger.debug("===========当前订单已点击回单===========>" + receipt.getOrderId());
                return R.error(-1,"当前订单已点击回单，请等待审核");
            }
            commonRedisLocks.lLeftPush(Constant.ORDER_RECEIPT, receipt.getOrderId());
            ReceiptDO receipts = receiptMapper.getByOrder(receipt.getOrderId());
            int save;
            if (receipts != null){
                return R.error(-1,"当前订单已申请回款");
            } else { 
                String fileName = StringUtils.getUUIDStr(20 ).toLowerCase();
                if (StringUtils.isBlank(receipt.getVoucherType())){
                    receipt.setVoucherType("png");
                }
                fileName += "." + receipt.getVoucherType();
                String path = UploadUtils.upload(url, fileName, "2", receipt.getVoucher());
                receipt.setVoucher(paths + path);

                receipt.setGmtCreate(new Date());
                receipt.setStatus(0);
                save = receiptMapper.save(receipt);
            }
            if(save != 1){
                return R.error(-1,"回单失败");
            }
            return R.ok();
        } finally {
            try{
                commonRedisLocks.lRemove(Constant.ORDER_RECEIPT, 0, receipt.getOrderId());
                commonRedisLock.unlock();
            }catch (Exception e) {
                logger.error("解锁异常=={}",e.getMessage());
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int confirmReceipt(OrderPayDO orderPay) throws Exception {
        int count = 0;
        logger.info("接收到用户确认收款信息："+JSON.toJSONString(orderPay));
        if (orderPay==null) {
            logger.debug("===========缺少订单参数===========>" + JSON.toJSONString(orderPay));
            throw new Exception("参数异常，缺少订单主键");
        }
        if (orderPay.getId() == null || orderPay.getId() == 0L){
            logger.debug("===========缺少订单参数===========>" + JSON.toJSONString(orderPay));
            throw new Exception("参数异常，缺少订单主键");
        }
        orderPay = orderPayMapper.get(orderPay.getId());
        CommonRedisLock commonRedisLock = null;
        CommonRedisLock commonRedisLocks = new CommonRedisLock(stringRedisTemplate);
        try{
            commonRedisLock = new CommonRedisLock(stringRedisTemplate, ORDER_ID_CONFIRM + orderPay.getId());
            if(!commonRedisLock.tryLock(3)){
                logger.debug("===========当前订单已经点击确认收款===========>" + orderPay.getId());
                return -2;
            }
            if (commonRedisLocks.searchListByValue(Constant.ORDER, orderPay.getOrderId())){
                logger.debug("===========当前订单正在回分===========>" + orderPay.getId());
                return -2;
            }
            commonRedisLocks.lLeftPush(Constant.ORDER, orderPay.getOrderId());
            //根据订单获取二维码信息
            PaymentCodeDO paymentCode = paymentCodeMapper.queryCodeByUrl(orderPay.getPayeeCode());
            if (paymentCode != null){
                //根据当前二维码获取二维码空单最大位数
                Map<String, Object> map = new HashMap<>();
                map.put("payeeId", paymentCode.getUserIdCreate());
                map.put("payeeCode", orderPay.getPayeeCode());
                int sort = orderPayMapper.queryOrderMaxSort(map);
                //获取当前订单空单位数
                map.put("id", orderPay.getId());
                int sortO = orderPayMapper.queryOrderMaxSort(map);
                if (sort != sortO){
                    paymentCodeMapper.updateEmptyCode(paymentCode.getCodeId(), paymentCode.getEmptyNumber()-1);
                } else {
                    paymentCodeMapper.updateEmptyCode(paymentCode.getCodeId(), 0);
                }
            }
            if (1 != orderPay.getStatus().intValue()){
                logger.debug("===========当前订单非未付款状态===========>" + orderPay.getId());
                count = -3;
            } else {
                //更新订单状态为已付款
                orderPay.setStatus(2);
                count = orderPayMapper.update(orderPay);
                OrderDO order = orderMapper.get(orderPay.getOrderId());
                order.setType(2);
                orderMapper.update(order);

                //成功为收款户恢复对应额度
                PayeeDO payee = payeeMapper.get(orderPay.getPayeeId());

                //验证是否订单超时
                boolean flag = false;
                if (!DateUtils.isOvertime(orderPay.getGmtCreate()) || 2 == order.getOvertimeStatus().intValue()){
                    flag = true;
                }


                //补单成功后验证当前商户是否需要自动下发
                MerchantDO merchant = merchantMapper.get(orderPay.getMerchantId());
                if (merchant.getLower() != 0 && merchant.getLowerMoney() <= orderPay.getOrderMoney()){
                    Constant.THREADPOOL.execute(new LowerTask(merchant, orderPay, bankMapper, quotaMapper, cashMapper));
                }
                //补单成功进行支付回调
                String notifyUrl = order.getNotifyUrl();
                if (StringUtils.isNotBlank(notifyUrl)){
                    Constant.THREADPOOL.execute(new RequestTask(merchant.getToken(), order, orderMapper));
                }
                //获取当前用户未回单数量
                List<OrderDO> list = orderMapper.getOrderByPayeeForNo(payee.getUserId());//获取未回单数量
                if (payee.getUncollectedQuantity().intValue() <= list.size()){
                    payee.setLineUpStatus(0);
                    payeeMapper.update(payee);
                    paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
                    if (paymentCode != null) {
                        //验证当前用户是否正在排队
                        boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(paymentCode.getUserIdCreate()));
                        if (f){
                            commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(paymentCode.getUserIdCreate()));
                            sendSortUtil.sendMsg(paymentCode.getPassagewayId());
                        }
                    }

                }

                JSONObject object = new JSONObject();
                object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                object.put("orderId", orderPay.getOrderId());
                if (flag){
                    //已超时恢复额度，需要扣除
                    object.put("type", 2);
                    object.put("money", orderPay.getOrderMoney());
                    object.put("userId", orderPay.getPayeeId());
                    object.put("reason", payee.getUserName() + "超时点击确认收款");
                    rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
                }
                object.put("type", 1);
                object.put("money", orderPay.getPayeeMoney());
                object.put("userId", orderPay.getPayeeId());
                object.put("reason", "订单佣金，" + payee.getUserName() + "点击确认收款");
                rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());

                QuotaDO quota = quotaMapper.get(orderPay.getPayeeAgentId());
                if (quota != null){
                    if (flag){
                        //已超时恢复额度，需要扣除
                        object.put("type", 2);
                        object.put("money", orderPay.getOrderMoney());
                        object.put("userId", orderPay.getPayeeAgentId());
                        object.put("reason", payee.getUserName() + "超时点击确认收款");
                        rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
                    }

                    object.put("type", 1);
                    object.put("money", orderPay.getPayeeMoney() + orderPay.getPayeeAgentMoney());
                    object.put("userId", orderPay.getPayeeAgentId());
                    object.put("reason", "订单佣金，" + payee.getUserName() + "点击确认收款");
                    rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
                }

                //新增商户余额
                object.put("type", 1);
                object.put("money", orderPay.getOrderMoney());
                object.put("userId", orderPay.getMerchantId());
                object.put("reason", "订单支付，" + payee.getUserName() + "点击确认收款");
                rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());

                object.put("type", 2);
                object.put("money", orderPay.getCountMoney());
                object.put("userId", orderPay.getMerchantId());
                object.put("reason", "订单手续费，" + payee.getUserName() + "点击确认收款");
                rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());

                //新增商户代理额度
                quota = quotaMapper.get(orderPay.getMerchantAgentId());
                if (quota != null && orderPay.getMerchantMoney() != null) {
                    object.put("type", 1);
                    object.put("money", orderPay.getMerchantMoney());
                    object.put("userId", orderPay.getMerchantAgentId());
                    object.put("reason", "订单支付，" + payee.getUserName() + "点击确认收款");
                    rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
                }

                //新增平台流水
                object.put("type", 1);
                object.put("money", orderPay.getPlatformMoney());
                object.put("userId", 2L);
                object.put("reason", "订单支付，" + payee.getUserName() + "点击确认收款");
                rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
            }
        } finally {
            try{
                commonRedisLocks.lRemove(Constant.ORDER, 0, orderPay.getOrderId());
                commonRedisLock.unlock();
            }catch (Exception e) {
                logger.error("解锁异常=={}",e.getMessage());
            }
        }
        return count;
    }

    @Override
    public R detailsOfBalance(String userId, String startTime, String endTime) throws Exception {
        logger.info("获取用户当前用户查询余额明细信息："+JSONObject.toJSONString(userId));
        if(StringUtils.isEmpty(userId)){
            return R.error(-1,"用户id为空");
        }

        if (StringUtils.isNotBlank(startTime)){
            startTime = DateUtils.getDateOfFormat(startTime, "yyyy-MM-dd") + " 00:00:00";
            endTime = DateUtils.getDateOfFormat(endTime, "yyyy-MM-dd") + " 23:59:59";
        }

        Map<String,Object> inputMap = new HashMap<>();
        inputMap.put("userId",Long.valueOf(userId));
        inputMap.put("startTime",startTime);
        inputMap.put("endTime",endTime);
        List<QuotaDO> detailsOfBalancelist = quotaMapper.list(inputMap);
        if(detailsOfBalancelist == null || detailsOfBalancelist.size() <= 0){
            return R.error(-1,"暂未查询到余额明细");
        }

        for(QuotaDO quota : detailsOfBalancelist){
            quota.setGmDate(DateUtils.formatDate(quota.getGmtDate()));
        }

        return R.ok(detailsOfBalancelist);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public R logout(String userId) throws Exception {
        logger.info("获取用户登出信息："+JSONObject.toJSONString(userId));
        PayeeDO payee = payeeMapper.get(Long.valueOf(userId));
        if(payee != null && 1 == payee.getLineUpStatus()){
            PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(Long.valueOf(userId));
            if(paymentCode != null){
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
                boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(paymentCode.getUserIdCreate()));
                if (f){
                    commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(paymentCode.getUserIdCreate()));
                    sendSortUtil.sendMsg(paymentCode.getPassagewayId());
                }
            }else{
                throw new Exception("当前用户无开启的收款码");
            }
            payee.setLineUpStatus(0);
            int update = payeeMapper.update(payee);
            if(update != 1){
                throw new Exception("当前用户排队状态修改失败");
            }
        }

        return R.ok();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public R changePassword(String userId, String newPassword, String oldPassword, String deviceId) throws Exception {
        logger.info("获取用户修改密码信息："+JSONObject.toJSONString(userId));
        UserDO user = userMapper.get(Long.valueOf(userId));
        PayeeDO payee = payeeMapper.get(user.getUserId());
        if (!deviceId.equals(payee.getDeviceId())){
            return R.error(-2,"当前用户登录设备异常，请联系管理员");
        }

        if(!user.getPassword().equals(MD5Utils.encrypt(user.getUsername(), oldPassword))){
            return R.error(-1,"您输入的旧密码有误！");
        }

        String nPassword = MD5Utils.encrypt(user.getUsername(), newPassword);
        user.setPassword(nPassword);
        int update = userMapper.update(user);
        if(update != 1){
            return R.error(-1,"密码修改错误");
        }

        payee.setPassword(nPassword);
        int update1 = payeeMapper.update(payee);
        if(update1 != 1){
            return R.error(-1,"密码修改错误");
        }
        return R.ok();
    }

    @Override
    public R personalInformation(String userId) throws Exception {
        logger.info("获取用户基本信息信息："+JSONObject.toJSONString(userId));
        if (StringUtils.isNotBlank(userId)){
            PayeeDO payee = payeeMapper.get(Long.valueOf(userId));
            if(payee == null){
                return R.error(-1,"用户信息查询失败");
            }
            return R.ok(payee);
        }
        logger.error("<======必填项未传======>");
        return R.error(-1, "系统异常");
    }

    @Override
    public R appUpdate() throws Exception{
        AppVersionDO appVersion = appVersionMapper.getNew();
        if(appVersion == null){
            return R.error(-1,"检查最新版失败");
        }
        return R.ok(appVersion);
    }


    @Override
    public R receiptState(String userId) throws Exception {
        logger.info("收到用户获取接单状态："+userId);
        PayeeDO payee = payeeMapper.get(Long.valueOf(userId));
        if(0 == payee.getStatus()){
            return R.error(-1,"当前用户为禁用状态，请联系管理员");
        }
        if(0 == payee.getLineStatus()){
            return R.error(-1,"当前用户不可接单，请联系管理员");
        }
        PayeeAgentDO payeeAgent = payeeAgentMapper.get(payee.getUserIdCreate());
        if(payeeAgent == null){
            return R.error(-1,"当前收款户无收款代理，请联系管理员");
        }
        if(0 == payeeAgent.getStatus()){
            return R.error(-1,"当前收款户代理已被禁用，请联系管理员");
        }

        QuotaDO quota = quotaMapper.get(payeeAgent.getUserId());
        if(quota.getActualQuota() <= 0){
            return R.error(-1,"当前收款户代理余额不足");
        }

        QuotaDO quotaDO = quotaMapper.get(payee.getUserId());
        if(quotaDO.getActualQuota() <= 0){
            return R.error(-1,"当前用户额度不足");
        }

        return R.ok();
    }

//    public void aaa(){
//        Map<String, Object> map = new HashMap<>();
//        map.put("receivingAccount", 1);
//        map.put("passagewayId", 1);
//        List<PaymentCodeDO> list = paymentCodeMapper.list(map);
//        for (PaymentCodeDO paymentCode : list) {
//            PayeeDO payee = payeeMapper.get(paymentCode.getUserIdCreate());
//            payee.setLineStatus(1);
//            payeeMapper.update(payee);
//
//            Map<String, String> paramMap = new HashMap<>();
//            paramMap.put("deviceId", payee.getDeviceId());
//            paramMap.put("userId", String.valueOf(payee.getUserId()));
//            paramMap.put("status", "1");
//            try {
//                String aaaa = HttpClientUtil.httpPost("http://122.10.18.186:8081/app/updateStatus", paramMap, "");
//                System.out.println("aaaa = " + aaaa);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }

}
